package vn.orderonline.com.core.business.restaurant;

import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mysql.jdbc.StringUtils;

import vn.orderonline.com.core.business.dto.ChooseDrinkDto;
import vn.orderonline.com.core.business.dto.ChooseFoodDto;
import vn.orderonline.com.core.business.dto.DrinkDto;
import vn.orderonline.com.core.business.dto.FoodDto;
import vn.orderonline.com.core.business.dto.RestaurantDto;
import vn.orderonline.core.commons.utils.DateUtils;
import vn.orderonline.core.dao.AdminDao;
import vn.orderonline.core.dao.CategoryDao;
import vn.orderonline.core.dao.CityDao;
import vn.orderonline.core.dao.DistrictDao;
import vn.orderonline.core.dao.DrinkDao;
import vn.orderonline.core.dao.FoodDao;
import vn.orderonline.core.dao.MenuDrinkDao;
import vn.orderonline.core.dao.MenuDrinkDrinkDao;
import vn.orderonline.core.dao.MenuFoodDao;
import vn.orderonline.core.dao.MenuFoodFoodDao;
import vn.orderonline.core.dao.RestaurantDao;
import vn.orderonline.core.dao.RestaurantMenuDrinkDao;
import vn.orderonline.core.dao.RestaurantMenuFoodDao;
import vn.orderonline.core.dao.entity.City;
import vn.orderonline.core.dao.entity.District;
import vn.orderonline.core.dao.entity.Drink;
import vn.orderonline.core.dao.entity.Food;
import vn.orderonline.core.dao.entity.MenuDrinkDrink;
import vn.orderonline.core.dao.entity.MenuFoodFood;
import vn.orderonline.core.dao.entity.Restaurant;
import vn.orderonline.core.dao.entity.RestaurantMenuDrink;
import vn.orderonline.core.dao.entity.RestaurantMenuFood;

@Service
@Transactional
public class RestaurantManagerImpl implements IRestaurantManager {

	@Autowired
	private RestaurantDao restaurantDao;
	@Autowired
	private RestaurantMenuFoodDao restaurantMenuFoodDao;
	@Autowired
	private MenuFoodFoodDao menuFoodFoodDao;
	@Autowired
	private FoodDao foodDao;
	@Autowired
	private MenuFoodDao menuFoodDao;
	@Autowired
	private RestaurantMenuDrinkDao restaurantMenuDrinkDao;
	@Autowired
	private MenuDrinkDao menuDrinkDao;
	@Autowired
	private MenuDrinkDrinkDao menuDrinkDrinkDao;
	@Autowired
	private DrinkDao drinkDao;
	@Autowired
	private CityDao cityDao;
	@Autowired
	private DistrictDao districtDao;
	@Autowired
	private CategoryDao categoryDao;
	@Autowired
	private AdminDao adminDao;

	@Override
	public List<RestaurantDto> search(RestaurantDto objSearch) {
		RestaurantDto result = null;
		List<RestaurantDto> listResult = new ArrayList<>();
		List<Restaurant> list = restaurantDao.search(
				objSearch.getRestaurantName(), objSearch.getRestaurantTitle(),
				objSearch.getWardName(), objSearch.getOpenTime(),
				objSearch.getCloseTime(), objSearch.getDeliveryPrice(),
				objSearch.getMinOrder());
		if (!list.isEmpty()) {
			for (Restaurant res : list) {
				result = new RestaurantDto();
				result.setRestaurantId(res.getRestaurantId());
				result.setRestaurantName(res.getRestaurantName());
				result.setRestaurantTitle(res.getRestaurantTitle());
				result.setWardName(res.getWardName());
				result.setOpenTime(String.valueOf(res.getOpenTime()));
				result.setCloseTime(String.valueOf(res.getCloseTime()));
				result.setDeliveryPrice(res.getDeliveryPrice());
				result.setMinOrder(res.getMinOrder());
				listResult.add(result);
			}
		}
		return listResult;
	}

	@Override
	public List<RestaurantDto> getAllRestaurants() {
		List<Restaurant> list = restaurantDao.findAll();
		List<RestaurantDto> result = new ArrayList<>();
		RestaurantDto obj = null;
		for (Restaurant res : list) {
			obj = new RestaurantDto();
			obj.setRestaurantId(res.getRestaurantId());
			obj.setRestaurantName(res.getRestaurantName());
			obj.setRestaurantTitle(res.getRestaurantTitle());
			obj.setWardName(res.getWardName());
			obj.setOpenTime(String.valueOf(res.getOpenTime()));
			obj.setCloseTime(String.valueOf(res.getCloseTime()));
			obj.setDeliveryPrice(res.getDeliveryPrice());
			obj.setMinOrder(res.getMinOrder());
			obj.setCreateId(res.getCreateId());
			obj.setUpdateId(res.getUpdateId());
			result.add(obj);
		}
		return result;
	}

	@Override
	public RestaurantDto getRestaurantById(Integer id, String property) {
		Restaurant res = restaurantDao.find(id);
		RestaurantDto dto = new RestaurantDto();
		if (res != null) {
			dto.setRestaurantId(res.getRestaurantId());
			dto.setRestaurantName(res.getRestaurantName());
			dto.setRestaurantTitle(res.getRestaurantTitle());
			dto.setWardName(res.getWardName());
			dto.setRestaurantImage(res.getRestaurantImage());
			dto.setOpenTime(String.valueOf(res.getOpenTime()));
			dto.setCloseTime(String.valueOf(res.getCloseTime()));
			dto.setDeliveryPrice(res.getDeliveryPrice());
			dto.setMinOrder(res.getMinOrder());
			dto.setRestaurantStatus(res.getRestaurantStatus());
			dto.setRestaurantNote(res.getRestaurantNote());
			dto.setDistrictId(res.getDistrictId());
			if (!StringUtils.isNullOrEmpty(res.getCreateId())) {
				String adminName = adminDao.getAdminNameByAccountName(res
						.getCreateId());
				if (!StringUtils.isNullOrEmpty(adminName)) {
					dto.setCreateId(adminName);
				} else {
					dto.setCreateId(res.getCreateId());
				}
			}
			if (!StringUtils.isNullOrEmpty(res.getUpdateId())) {
				String adminName = adminDao.getAdminNameByAccountName(res
						.getUpdateId());
				if (!StringUtils.isNullOrEmpty(adminName)) {
					dto.setUpdateId(adminName);
				} else {
					dto.setUpdateId(res.getUpdateId());
				}
			}
			dto.setCreateTime(DateUtils.timestampToString(res.getCreateTime(), "dd/MM/yyyy HH:mm:ss"));
			if (res.getUpdateTime() != null) {
				dto.setUpdateTime(DateUtils.timestampToString(res.getUpdateTime(), "dd/MM/yyyy HH:mm:ss"));
			}
			String districtName = "";
			String category = "";
			if (property.equals("detail")) {
				if (!StringUtils.isNullOrEmpty(res.getDeliveryHome())) {
					String districtList = res.getDeliveryHome();
					String[] arrStr = districtList.split(",");
					int length = arrStr.length;
					for (int i = 0; i < length; i++) {
						districtName += districtDao.find(
								Integer.valueOf(arrStr[i])).getDistrictName()
								+ ", ";
					}
				}
				if (!StringUtils.isNullOrEmpty(res.getCategoryIds())) {
					String cateList = res.getCategoryIds();
					String[] arrCate = cateList.split(",");
					int length = arrCate.length;
					for (int i = 0; i < length; i++) {
						category += categoryDao.find(
								Integer.valueOf(arrCate[i])).getCategoryName()
								+ ", ";
					}
					dto.setDeliveryHome(districtName);
					dto.setCategoryIds(category);
				}
			} else if (property.equals("update")) {
				dto.setDeliveryHome(res.getDeliveryHome());
				dto.setCategoryIds(res.getCategoryIds());
			}
			District dis = districtDao.find(res.getDistrictId());
			if (dis != null) {
				dto.setDistrictName(dis.getDistrictName());
				dto.setCityId(dis.getCityId());
			}
			City city = cityDao.find(dto.getCityId());
			dto.setCityName(city.getCityName());
		}
		return dto;
	}

	@Override
	public void add(RestaurantDto res) {
		Restaurant rest = new Restaurant();
		rest.setRestaurantName(res.getRestaurantName());
		rest.setRestaurantTitle(res.getRestaurantTitle());
		rest.setWardName(res.getWardName());
		rest.setRestaurantImage(res.getRestaurantImage());
		rest.setOpenTime(Time.valueOf(res.getOpenTime() + ":00"));
		rest.setCloseTime(Time.valueOf(res.getCloseTime() + ":00"));
		rest.setDeliveryPrice(res.getDeliveryPrice());
		rest.setMinOrder(res.getMinOrder());
		rest.setCreateTime(new Timestamp(DateUtils.now()));
		rest.setCreateId(res.getCreateId());
		rest.setRestaurantStatus(1);
		rest.setRestaurantNote(res.getRestaurantNote());
		rest.setDistrictId(res.getDistrictId());
		rest.setRestaurantImage(res.getRestaurantImage());
		rest.setDeliveryHome(res.getDeliveryHome());
		rest.setCategoryIds(res.getCategoryIds());
		restaurantDao.save(rest);
	}

	@Override
	public Boolean checkExistedRestaurant(String restaurantName) {
		if (!StringUtils.isNullOrEmpty(restaurantName)) {
			return restaurantDao.checkExistedRestaurant(restaurantName.trim());
		}
		return false;
	}

	@Override
	public void delete(Integer id) {

		List<RestaurantMenuFood> rmfList = restaurantMenuFoodDao
				.getListRestaurantMenuFoodByResId(id);
		if (!rmfList.isEmpty()) {
			for (RestaurantMenuFood rmf : rmfList) {
				restaurantMenuFoodDao.delete(rmf);

				List<MenuFoodFood> listMff = menuFoodFoodDao
						.getListMenuFoodFoodByMenuFoodId(rmf
								.getRestaurantMenuFoodId().getMenuFoodId());
				for (MenuFoodFood mff : listMff) {
					menuFoodFoodDao.delete(mff);
					foodDao.delete(foodDao.find(mff.getId().getFoodId()));
				}

				menuFoodDao.delete(menuFoodDao.find(rmf
						.getRestaurantMenuFoodId().getMenuFoodId()));
			}
		}

		List<RestaurantMenuDrink> rmdList = restaurantMenuDrinkDao
				.getListRestaurantMenuDrinkByResId(id);
		if (!rmdList.isEmpty()) {
			for (RestaurantMenuDrink rmd : rmdList) {
				restaurantMenuDrinkDao.delete(rmd);

				List<MenuDrinkDrink> mddList = menuDrinkDrinkDao
						.getListMenuDrinkDrinkByMenuDrinkId(rmd.getId()
								.getMenuDrinkId());
				for (MenuDrinkDrink mdd : mddList) {
					menuDrinkDrinkDao.delete(mdd);
					drinkDao.delete(drinkDao.find(mdd.getId().getDrinkId()));
				}

				menuDrinkDao.delete(menuDrinkDao.find(rmd.getId()
						.getMenuDrinkId()));
			}
		}

		Restaurant res = restaurantDao.find(id);
		if (id != null) {
			restaurantDao.delete(res);
		}
	}

	@Override
	public Boolean update(RestaurantDto res) {
		if (res != null) {
			Restaurant rest = restaurantDao.find(res.getRestaurantId());
			if (rest != null) {
				rest.setRestaurantTitle(res.getRestaurantTitle());
				rest.setWardName(res.getWardName());
				rest.setRestaurantImage(res.getRestaurantImage());
				rest.setOpenTime(Time.valueOf(res.getOpenTime()));
				rest.setCloseTime(Time.valueOf(res.getCloseTime()));
				rest.setDeliveryPrice(res.getDeliveryPrice());
				rest.setMinOrder(res.getMinOrder());
				rest.setUpdateTime(new Timestamp(DateUtils.now()));
				rest.setUpdateId(res.getUpdateId());
				rest.setRestaurantNote(res.getRestaurantNote());
				rest.setDistrictId(res.getDistrictId());
				rest.setCategoryIds(res.getCategoryIds());
				rest.setDeliveryHome(res.getDeliveryHome());
				restaurantDao.update(rest);
				return true;
			}
		}
		return false;
	}

	@Override
	public Map<String, String> getAllRestaurantIdAndName() {

		List<Object[]> list = restaurantDao.getAllRestaurantIdAndName();
		Map<String, String> map = new LinkedHashMap<>();
		for (Object[] obj : list) {
			map.put(obj[0].toString(), obj[1].toString());
		}
		return map;
	}

	@Override
	public List<RestaurantDto> findRestaurantByCityIdAndDeliverHome(
			Integer cityId, String deliveryHome) {
		List<RestaurantDto> listRes = new ArrayList<>();
		if (cityId != null && !StringUtils.isNullOrEmpty(deliveryHome)) {
			List<Object[]> list = restaurantDao.findRestaurantByCityId(cityId);
			if (!list.isEmpty()) {
				RestaurantDto dto = null;
				for (Object[] obj : list) {
					dto = new RestaurantDto();
					dto.setDistrictName((String) obj[0]);
					Restaurant res = (Restaurant) obj[1];
					dto.setRestaurantId(res.getRestaurantId());
					dto.setRestaurantName(res.getRestaurantName());
					dto.setRestaurantTitle(res.getRestaurantTitle());
					dto.setWardName(res.getWardName());
					dto.setRestaurantImage(res.getRestaurantImage());
					dto.setOpenTime(String.valueOf(res.getOpenTime()));
					dto.setCloseTime(String.valueOf(res.getCloseTime()));
					dto.setDeliveryPrice(res.getDeliveryPrice());
					dto.setMinOrder(res.getMinOrder());
					dto.setRestaurantStatus(res.getRestaurantStatus());
					dto.setCategoryIds(res.getCategoryIds());
					String deHome = res.getDeliveryHome();
					if (!StringUtils.isNullOrEmpty(deHome)) {
						String[] arrCategory = deHome.split(",");
						boolean flag = false;
						int length = arrCategory.length;
						for (int i = 0; i < length; i++) {
							if (arrCategory[i].equals(deliveryHome)) {
								flag = true;
								break;
							}
						}
						if (flag) {
							listRes.add(dto);
						}
					}
				}
			}
		}
		return listRes;
	}

	@Override
	public String getRestaurantNameByRestaurantId(Integer restaurantId) {
		if (restaurantId != null) {
			return restaurantDao.getRestaurantNameByRestaurantId(restaurantId);
		}
		return null;
	}

	@Override
	public List<ChooseFoodDto> chooseFood(Integer resId) {
		List<ChooseFoodDto> listChooseFoodDto = new ArrayList<>();
		ChooseFoodDto chooseFoodDto = null;
		List<Object[]> list = menuFoodDao.getListMenuFoodByRestaurantId(resId);
		if (!list.isEmpty()) {
			for (Object[] obj : list) {
				chooseFoodDto = new ChooseFoodDto();
				chooseFoodDto.setMenuFoodId((Integer) obj[2]);
				chooseFoodDto.setMenuFoodName((String) obj[3]);
				List<Object[]> listFood = foodDao
						.getListFoodByRestaurantIdAndMenuFoodId(resId,
								(Integer) obj[2]);
				List<FoodDto> listFoodDto = new ArrayList<>();
				FoodDto foodDto = null;
				if (!listFood.isEmpty()) {
					for (Object[] objf : listFood) {
						foodDto = new FoodDto();
						Food food = (Food) objf[4];
						if (food != null) {
							foodDto.setFoodId(food.getFoodId());
							foodDto.setFoodName(food.getFoodName());
							foodDto.setFoodImage(food.getFoodImage());
							foodDto.setFoodTitle(food.getFoodTitle());
							foodDto.setOldPrice(food.getOldPrice());
							foodDto.setNewPrice(food.getNewPrice());
						}
						listFoodDto.add(foodDto);
					}
				}
				chooseFoodDto.setListFoodDto(listFoodDto);
				listChooseFoodDto.add(chooseFoodDto);
			}
		}
		return listChooseFoodDto;
	}

	@Override
	public List<ChooseDrinkDto> chooseDrink(Integer resId) {
		List<ChooseDrinkDto> listChooseDrinkDto = new ArrayList<>();
		ChooseDrinkDto chooseDrinkDto = null;
		List<Object[]> list = menuDrinkDao.getListMenuDrinkByResId(resId);
		if (!list.isEmpty()) {
			for (Object[] obj: list) {
				chooseDrinkDto = new ChooseDrinkDto();
				chooseDrinkDto.setMenuDrinkId((Integer) obj[2]);
				chooseDrinkDto.setMenuDrinkName((String) obj[3]);
				List<Object[]> listDrink = drinkDao.getListDrinkByResIdAndMenuDrinkId(resId, (Integer) obj[2]);
				List<DrinkDto> listDrinkDto = new ArrayList<>();
				DrinkDto drinkDto = null;
				if (!listDrink.isEmpty()) {
					for (Object[] objd : listDrink) {
						drinkDto = new DrinkDto();
						Drink drink = (Drink) objd[4];
						if (drink != null) {
							drinkDto.setDrinkId(drink.getDrinkId());
							drinkDto.setDrinkName(drink.getDrinkName());
							drinkDto.setDrinkImage(drink.getDrinkImage());
							drinkDto.setDrinkTitle(drink.getDrinkTitle());
							drinkDto.setOldPrice(drink.getOldPrice());
							drinkDto.setNewPrice(drink.getNewPrice());
						}
						listDrinkDto.add(drinkDto);
					}
				}
				chooseDrinkDto.setListDrinkDto(listDrinkDto);
				listChooseDrinkDto.add(chooseDrinkDto);
			}
		}
		return listChooseDrinkDto;
	}

	@Override
	public List<String> getMenu(Integer resId) {
		List<String> list = new ArrayList<>();
		list.addAll(menuFoodDao.getMenuFoodNameByResId(resId));
		list.addAll(menuDrinkDao.getMenuDrinkNameByResId(resId));
		return list;
	}

}
